﻿using System.Linq.Expressions;
using System.Reflection;

namespace PmSoft.Core.Reflection;

/// <summary>
/// 表示成员表达式模型的接口
/// </summary>
public interface IMemberExpressionModel
{
	/// <summary>
	/// 获取成员名称
	/// </summary>
	string Name { get; }

	/// <summary>
	/// 获取成员类型
	/// </summary>
	Type Type { get; }

	/// <summary>
	/// 获取成员的表达式
	/// </summary>
	/// <param name="source">源表达式</param>
	/// <returns>成员的表达式</returns>
	Expression GetExpression(Expression source);

	/// <summary>
	/// 设置成员的表达式
	/// </summary>
	/// <param name="source">源表达式</param>
	/// <param name="value">值表达式</param>
	/// <returns>设置成员的表达式</returns>
	Expression SetExpression(Expression source, Expression value);
}

/// <summary>
/// 字段表达式模型
/// </summary>
internal sealed class FieldExpressionModel : IMemberExpressionModel
{
	private readonly FieldInfo _fieldInfo;

	/// <summary>
	/// 初始化 FieldExpressionModel 类的新实例
	/// </summary>
	/// <param name="fieldInfo">字段信息</param>
	public FieldExpressionModel(FieldInfo fieldInfo)
	{
		_fieldInfo = fieldInfo;
	}

	/// <summary>
	/// 获取字段名称
	/// </summary>
	public string Name => _fieldInfo.Name;

	/// <summary>
	/// 获取字段类型
	/// </summary>
	public Type Type => _fieldInfo.FieldType;

	/// <summary>
	/// 获取字段的表达式
	/// </summary>
	/// <param name="source">源表达式</param>
	/// <returns>字段的表达式</returns>
	public Expression GetExpression(Expression source)
	{
		return Expression.Field(source, _fieldInfo);
	}

	/// <summary>
	/// 设置字段的表达式
	/// </summary>
	/// <param name="source">源表达式</param>
	/// <param name="value">值表达式</param>
	/// <returns>设置字段的表达式</returns>
	public Expression SetExpression(Expression source, Expression value)
	{
		return Expression.Assign(GetExpression(source), value);
	}
}

/// <summary>
/// 属性表达式模型
/// </summary>
internal sealed class PropertyExpressionModel : IMemberExpressionModel
{
	private readonly PropertyInfo _propertyInfo;

	/// <summary>
	/// 初始化 PropertyExpressionModel 类的新实例
	/// </summary>
	/// <param name="propertyInfo">属性信息</param>
	public PropertyExpressionModel(PropertyInfo propertyInfo)
	{
		_propertyInfo = propertyInfo;
	}

	/// <summary>
	/// 获取属性名称
	/// </summary>
	public string Name => _propertyInfo.Name;

	/// <summary>
	/// 获取属性类型
	/// </summary>
	public Type Type => _propertyInfo.PropertyType;

	/// <summary>
	/// 获取属性的表达式
	/// </summary>
	/// <param name="source">源表达式</param>
	/// <returns>属性的表达式</returns>
	public Expression GetExpression(Expression source)
	{
		return Expression.Property(source, _propertyInfo);
	}

	/// <summary>
	/// 设置属性的表达式
	/// </summary>
	/// <param name="source">源表达式</param>
	/// <param name="value">值表达式</param>
	/// <returns>设置属性的表达式</returns>
	public Expression SetExpression(Expression source, Expression value)
	{
		return Expression.Assign(GetExpression(source), value);
	}
}


